﻿using SuperX.Common.BasicService;
using SuperX.Common.Log;
using System;
using System.Collections.Generic;
using System.Text;

namespace SuperX.Common.Scheduler
{

    // 
    public class ValueChangedDispatcher : IScheduler, IDisposable
    {
        // 
        public SchedulerPattern Pattern
        {
            get
            {
                return SchedulerPattern.Changed;
            }
        }

        // 
        public ITag Tag { get; set; }

        // 
        public ValueChangedDispatcher(SchedulerSetting setting, string tagPath, bool isUseEvent = false)
        {
            this._isUseEvent = isUseEvent;
            this._deadZone = setting.DeadZone;
            if (!this._project.Objects.ContainsKey(tagPath))
            {
                return;
            }
            this.Tag = (this._project.Objects[tagPath] as ITag);
        }

        // 
        private void CheckValue()
        {
            if (BasicServiceManager.GetProjService().Project.Status != ControllerStatus.Running)
            {
                return;
            }
            if (this._deadZone != 0.0 && this.Tag is IRealTag && !(this.Tag.Value is DateTime))
            {
                if (Math.Abs(Convert.ToDouble(this.Tag.Value) - Convert.ToDouble(this._lastValue)) >= this._deadZone)
                {
                    this.Invoke();
                    this._lastValue = this.Tag.Value;
                    return;
                }
            }
            else
            {
                this.Invoke();
                this._lastValue = this.Tag.Value;
            }
        }

        // 
        public void Invoke()
        {
            SchedulerValue obj = new SchedulerValue
            {
                TriggerTime = DateTime.Now,
                TagPath = this.Tag.FullName,
                Vale = this.Tag.Value,
                TimeStamp = this.Tag.TimeStamp,
                Quality = this.Tag.Quality
            };
            this._action(obj);
        }

        // 
        public void Register(Action<SchedulerValue> action)
        {
            this._action = action;
            this.Run(this._project.StartTime);
        }

        //
        public bool Run(DateTime time)
        {
            if (this.Tag == null || this._action == null || this._isRun)
            {
                return false;
            }
            this._lastValue = this.Tag.Value;
            if (this._isUseEvent)
            {
              
            }
            this._isRun = true;
            return true;
        }

        // 
        private void TagValueChanged(object sender, TagChangedEventArgs e)
        {
            try
            {
                this.CheckValue();
            }
            catch (Exception exception)
            {
                Logger.WarnException(exception);
            }
        }

        // 
        public void Stop()
        {
            this.Dispose();
            this._isRun = false;
        }

        // 
        public void Dispose()
        {
            if (this._isUseEvent && this.Tag != null)
            {
                
            }
        }

        // 
        public bool Check(out SchedulerValue dispatchValue)
        {
            dispatchValue = null;
            if (this._isRun && !this._isUseEvent && !object.Equals(this._lastValue, this.Tag.Value))
            {
                this.CheckValue();
            }
            return false;
        }

        // 
        public void Invoke(SchedulerValue dispatchValue)
        {
        }

        //
        private readonly IProject _project = BasicServiceManager.GetProjService().Project;

        //
        private Action<SchedulerValue> _action;

        // 
        private bool _isRun;

        // 
        private double _deadZone;

        // 
        private object _lastValue;

        // 
        private bool _isUseEvent;
    }
}
